#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <atomic>
#include <fstream>
#include <boost/algorithm/string.hpp>
// 本文件实现通用的工具
namespace ns_util
{
    
    // 声明
    class PathUtil;
    class FileUtil;
    class TimeUtil;
    const static std::string dir = "./temp/";
    // 时间工具
    class TimeUtil
    {
    public:
        // 获取时间戳，以字符串的形式获取
        static std::string GetTimeStamp()
        {
            struct timeval outtime;
            ::gettimeofday(&outtime, nullptr);
            return std::to_string(outtime.tv_sec);
        }
        static std::string GetTimeStampMs()
        {
            struct timeval outtime;
            ::gettimeofday(&outtime, nullptr);
            return std::to_string(outtime.tv_sec * 1000);
        }
    };
    // 文件路径工具
    class PathUtil
    {
        static std::string AddSuffix(std::string &filename, std::string suffix)
        {
            std::string pathname = "";
            pathname += dir;
            pathname += filename;
            pathname += suffix;
            return pathname;
        }

    public:
        /***********编译时用到的临时文件*************/

        // 根据文件名获取完整的文件格式："aaa" -> "./temp/aaa.cpp"
        static std::string Src(std::string filename)
        {
            return AddSuffix(filename, ".cpp");
        }
        // 根据文件名获取最终目标的文件名："aaa"->"./temp/aaa.exe"
        static std::string Exe(std::string filename)
        {
            return AddSuffix(filename, ".exe");
        }
        static std::string CmErr(std::string filename)
        {
            return AddSuffix(filename, ".complier_err");
        }

        /**********运行时用到的临时文件 **************/

        // 根据文件名获取错误信息的文件名："aaa"->"./temp/aaa.stderr"
        static std::string Err(std::string filename)
        {
            return AddSuffix(filename, ".stderr");
        }

        static std::string Stdin(std::string filename)
        {
            return AddSuffix(filename, ".stdin");
        }
        static std::string Stdout(std::string filename)
        {
            return AddSuffix(filename, ".stdout");
        }
    };

    // 文件工具
    class FileUtil
    {
    public:
        static bool isFileExist(std::string pathname)
        {
            struct stat result;
            if (::stat(pathname.c_str(), &result) == 0)
            {
                return true;
            }
            return false;
        }
        // 形成唯一的文件名
        static std::string UniqueFileName()
        {
            static std::atomic_uint id(0);
            ++id;
            // 生成唯一文件名：毫秒级时间戳+递增器

            std::string a = TimeUtil::GetTimeStampMs();
            std::string b = std::to_string(id);
            return a + "_" + b;
        }
        static bool WriteFile(const std::string &filename, std::string &code)
        {
            std::ofstream out(filename);
            if (!out.is_open())
            {
                return false;
            }

            out.write(code.c_str(), code.size());
            out.close();
            return true;
        }
        static bool ReadFile(const std::string &filename, std::string *content, bool keep = false)
        {
            (*content).clear();

            std::ifstream in(filename);
            if (!in.is_open())
            {
                std::cout << "打开文件失败" << filename<<std::endl; 
                return false;
            }
            std::cout << "正在读取：" << filename << std::endl;
            std::string line;
            while (std::getline(in, line))
            {
                // 按行读
                (*content) += line;
                (*content) += (keep ? "\n" : "");
            }

            return true;
        }
    };
    //字符串工具
    class StringUtil
    {
        public:
        /**
         * str:输入型参数,待分割的字符串
         * content:输出型参数，是一个vector，里面保存分割完的字符串
         * sep:分割符
         */
        static bool Split(const std::string& str,std::vector<std::string>* content,const std::string& sep)
        {
            boost::split((*content),str,boost::is_any_of(sep),boost::algorithm::token_compress_on);
            return true;
        }
    };
}